package top.frsf.tank;

import top.frsf.GameObject;
import top.frsf.GamePanel;
import top.frsf.bullet.Bullet;
import top.frsf.envir.Wall;
import top.frsf.tool.Direction;

import java.awt.*;
import java.util.ArrayList;

/**
 * @BelongsProject: TankWar1
 * @BelongsPackage: top.frsf.tank
 * @Author: FRSF
 * @CreateTime: 2022-09-03  10:02
 * @Description: tank抽象父类
 * @Version: 1.0
 */
public abstract class TankObj extends GameObject {
    // 实体尺寸
    int width = 60;
    int height = 60;

    // 速度
    int speed = 3;

    // 方向
    Direction direction = Direction.RIGHT;

    // 生命，防止死亡后仍能触发键盘事件，发射子弹
    public boolean alive = false;

    // tank四方向图像
    private String upImage;
    private String downImage;
    private String leftImage;
    private String rightImage;

    // tank攻击冷却状态
    private boolean attackCoolDown = true;
    // tank攻击冷却时间
    private int attackCoolDownTime = 500;


    public TankObj(String img, int x, int y, GamePanel gamePanel,
                   String upImage, String downImage, String leftImage, String rightImage) {
        super(img, x, y, gamePanel);
        this.upImage = upImage;
        this.downImage = downImage;
        this.leftImage = leftImage;
        this.rightImage = rightImage;
    }

    @Override
    public abstract void paintSelf(Graphics g);

    @Override
    public abstract Rectangle getRec();

    public void setImg(String img) {
        this.img = Toolkit.getDefaultToolkit().getImage(img);
    }

    /*tank 坐标移动*/
    public void upward() {
        direction = Direction.UP;
        setImg(upImage);
        if (!hitWall(x, y - speed) && !moveToBorder(x, y - speed))
            y -= speed;
    }

    public void downward() {
        direction = Direction.DOWN;
        setImg(downImage);
        if (!hitWall(x, y + speed) && !moveToBorder(x, y + speed))
            y += speed;
    }

    public void leftward() {
        direction = Direction.LEAF;
        setImg(leftImage);
        if (!hitWall(x - speed, y) && !moveToBorder(x - speed, y))
            x -= speed;
    }

    public void rightward() {
        direction = Direction.RIGHT;
        setImg(rightImage);
        if (!hitWall(x + speed, y) && !moveToBorder(x + speed, y))
            x += speed;
    }

    /* 坦克头部坐标获取，用于发射子弹起始位置 */
    public Point getHeadPoint() {
        switch (direction) {
            case LEAF:
                return new Point(x, y + height / 2);
            case RIGHT:
                return new Point(x + width, y + height / 2);
            case UP:
                return new Point(x + width / 2, y);
            case DOWN:
                return new Point(x + width / 2, y + height);
            default:
                return null;
        }
    }


    /* 发射子弹 */
    public void attack() {
        if (attackCoolDown && alive) {
            Point p = getHeadPoint();
            Bullet but = new Bullet("src/main/resources/bullet/userbullet.png",
                    p.x - 7, p.y - 7, this.gamePanel, this.direction);
            this.gamePanel.bulletList.add(but);

            // 启动冷却计算线程
            new AttackCD().start();
        }

    }

    /* 添加新线程，计算tank发射冷却时间 */
    class AttackCD extends Thread {
        @Override
        public void run() {
            // 设置为冷却状态
            attackCoolDown = false;
            try {
                Thread.sleep(attackCoolDownTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 解除攻击冷却
            attackCoolDown = true;
            // 线程终止
            this.stop();
        }
    }

    /* tank与围墙碰撞检测 原理：不能向原方向移动，用tank下一步坐标进行提前检测，若撞墙则tanK坐标不改变 */
    public boolean hitWall(int x, int y) {
        // 围墙列表
        ArrayList<Wall> wallList = this.gamePanel.wallList;
        // 下一步位置
        Rectangle next = new Rectangle(x, y, width, height);
        for (Wall wall : wallList) {
            if (next.intersects(wall.getRec())) {
                // 发生碰撞
                return true;
            }
        }
        return false;
    }

    /* tank与边界碰撞检测 */
    public boolean moveToBorder(int x, int y) {
        return x < 0 || y < 0 || x + width > this.gamePanel.getWidth()
                || y + height > this.gamePanel.getHeight();
    }


}
